package com.hwj.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.github.pagehelper.util.StringUtil;
import com.hwj.entity.Permission;
import com.hwj.entity.Role;
import com.hwj.entity.RolePermission;
import com.hwj.entity.User;
import com.hwj.exception.CustomAuthException;
import com.hwj.service.PermissionService;
import com.hwj.service.RolePermissionService;
import com.hwj.service.RoleService;
import com.hwj.service.UserInfoService;
import com.hwj.utils.JsonResponse;
import com.hwj.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

import static com.aliyun.teautil.Common.assertAsString;
import static java.util.Arrays.asList;

@RestController
@Slf4j
@CrossOrigin
@RequestMapping("sms")
public class AliyunSmSController {
    @Autowired
    UserInfoService userInfoService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    RoleService roleService;
    @Autowired
    RolePermissionService rolePermissionService;
    @Autowired
    PermissionService permissionService;

    private Client createClient() throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，您的 AccessKey ID
                .setAccessKeyId("LTAI5tGCwRyKi21JNv3zB1Ti")
                // 必填，您的 AccessKey Secret
                .setAccessKeySecret("NxUTzJs2fsOagNHMO5Ky5IxmQNNxYp");
        // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new Client(config);
    }

    private User getUserDetail(User user){
        HashSet<Permission> permissionSet = new HashSet<>();
        Long roleId= user.getRoleId();
        // 根据roleId从role_permission表查询出所有的permissionId
        List<RolePermission> rolePermissions = rolePermissionService.queryByRoleId(roleId);
        for (RolePermission rolePermission : rolePermissions) {
            Long permissionId = rolePermission.getPermissionId();
            // 根据permissionId查询permission信息
            Permission permission = permissionService.selectByPrimaryKey(permissionId);
            permissionSet.add(permission);
        }
        log.info("permissionSet " + permissionSet);
        Role role = roleService.selectByPrimaryKey(user.getRoleId());
        user.setRoleDescribe(role.getRoleDescribe());
        // 对资源根据id进行排序
        LinkedHashSet<Permission> sortedSet = permissionSet.stream().sorted(Comparator.comparing(Permission::getPermissionId)).collect(Collectors.toCollection(LinkedHashSet::new));
        //设置当前用户的资源信息
        log.info("sortedSet: " + sortedSet);
        user.setPermissions(sortedSet);
        //String token = JWT.create().setExpiresAt(DateUtil.offsetDay(new Date(), 1)).setAudience(user.getUserid()+"").setKey(SecureUtil.md5(user.getUserpass()).getBytes()).sign();
        String token = JWT.create().setExpiresAt(DateUtil.offsetDay(new Date(), 1)).setPayload("userId", user.getUserId()).setKey(user.getPassword().getBytes()).sign();
        //Algorithm.HMAC256(user.getPassword())
        user.setToken(token);
        //测试security中的user
        log.info("security :" + SecurityContextHolder.getContext().getAuthentication());
        return user;
    }

    /**
     * 获取验证码
     * @param phone
     * @return
     * @throws Exception
     */
    @GetMapping("")
    public JsonResponse getCode(String phone) throws Exception {
        //判断传入参数信息
        if(StrUtil.isBlank(phone)){
            return JsonResponse.failResponse(-2,"手机号为空",null);
        }

        //阿里云sms
        Client client = createClient();
        /*验证码*/
        String code=1000 +new Random().nextInt(9000)+"";

        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setSignName("宠物分享论坛")
                .setTemplateCode("SMS_464740872")
                .setPhoneNumbers(phone)
                .setTemplateParam("{\"code\":\""+code+"\"}");
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
        } catch (TeaException error) {
            // 错误 message
            log.error(error.getMessage());
            // 诊断地址
            log.error( error.getData().get("Recommend")+"");
            assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 错误 message
            log.error(error.getMessage());
            // 诊断地址
            log.error(error.getData().get("Recommend")+"");
            assertAsString(error.message);
        }
        //缓存到redis中
        redisUtil.set("phone"+phone,code,300);
        return JsonResponse.successResponse(0,"发送短信成功",null);
    }

    /**
     * 手机号登陆
     * @param loginBody
     * @return
     */
    @PostMapping("/login")
    public JsonResponse loginByPhone(@RequestBody Map<String,String> loginBody){
        //手机号登陆参数
        String phone=loginBody.get("phone");
        String code=loginBody.get("code");
        if(StrUtil.isBlank(phone)||StrUtil.isBlank(code)){
            return JsonResponse.failResponse(-2,"登陆参数为空",null);
        }
        //判断手机号是否存在数据库
        User user=new User();
        user.setPhone(phone);
        user = userInfoService.queryByNamePhoneEmail(user, 1, 1)
                .getList()
                .stream()
                .findFirst()
                .orElseThrow(() -> new CustomAuthException("该手机号尚未注册"));
        //与redis缓存的code对比校验
        String codeCache = Convert.toStr(redisUtil.get("phone" + phone));
        if(StrUtil.isNotBlank(codeCache)&&codeCache.equals(code)){
            User userDetail = getUserDetail(user);
            redisUtil.del("phone" + phone);
            return JsonResponse.successResponse(0,"登陆成功",userDetail);
        }else {
            return JsonResponse.failResponse(-2,"验证码错误或已失效",null);
        }
    }

    /**
     * 注册
     * @param loginBody
     * @return
     */
    @PostMapping("/register")
    public JsonResponse registerByPhone(@RequestBody Map<String,String> loginBody){
        //手机号登陆参数
        String phone=loginBody.get("phone");
        String code=loginBody.get("code");
        //与redis缓存的code对比校验
        String codeCache = Convert.toStr(redisUtil.get("phone" + phone));
        if(StrUtil.isNotBlank(codeCache)&&codeCache.equals(code)){
            if(StrUtil.isBlank(phone)||StrUtil.isBlank(code)){
                return JsonResponse.failResponse(-2,"注册参数为空",null);
            }
            //判断手机号是否存在数据库
            User user=new User();
            user.setPhone(phone);
            List<User> list = userInfoService.queryByNamePhoneEmail(user, 1, 1).getList();
            if(CollectionUtil.isNotEmpty(list)){
                return JsonResponse.failResponse(-2,"该手机号已被注册",null);
            }
            //设置默认密码和其他一些默认信息
            user.setPhone(phone);
            user.setPassword(new BCryptPasswordEncoder().encode("123456"));
            String uuid=1000 +new Random().nextInt(9000)+"";
            user.setRealName("用户"+uuid);
            user.setProfile("我是一个特别喜欢宠物的一个人，希望大家与我交朋友~");
            user.setAvatar("https://img2.baidu.com/it/u=1504791015,2700524207&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500");
            userInfoService.insertSelective(user);
            redisUtil.del("phone" + phone);
            return JsonResponse.successResponse(0,"注册成功！默认密码：123456,请重新登陆",null);
        }else {
            return JsonResponse.failResponse(-2,"验证码错误或已失效",null);
        }

    }


}
